package com.tracelog.core.config;

import com.tracelog.core.enums.IncludeType;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.*;
import java.util.regex.Pattern;

/**
 * TraceLog配置属性
 *
 * @author tracelog
 * @since 1.0.0
 */
@Data
@ConfigurationProperties(prefix = "trace-log")
public class TraceLogProperties {

    /**
     * 是否启用
     */
    private boolean enabled = true;

    /**
     * 是否缓存请求体（通过过滤器实现）
     */
    private boolean cacheRequestBody = true;

    /**
     * 是否启用跟踪ID
     */
    private boolean enableTraceId = true;

    /**
     * 包含的信息
     */
    private Set<IncludeType> includes = new HashSet<>(IncludeType.defaultIncludes());

    /**
     * 排除的路径模式（使用Ant风格的路径模式）
     */
    private List<String> excludePatterns = new ArrayList<>();

    /**
     * 敏感字段（全局）
     */
    private Set<String> sensitiveFields = new HashSet<>(
        Arrays.asList("password", "pwd", "secret", "token", "authorization"));

    /**
     * 大对象检测阈值（字节）
     * 当响应超过此大小时，不记录完整响应内容，仅记录大小信息
     */
    private int largeObjectThreshold = 10 * 1024; // 10KB

    /**
     * 是否启用异步日志记录
     */
    private boolean async = true;

    /**
     * 是否启用控制台输出
     */
    private boolean printToConsole = true;

    /**
     * 是否启用文件输出
     */
    private boolean fileOutput = false;

    /**
     * 日志文件路径
     */
    private String logFilePath = "logs/tracelog.log";

    /**
     * 是否脱敏敏感信息
     */
    private boolean maskSensitiveInfo = true;
    
    /**
     * 是否记录异常堆栈
     */
    private boolean recordExceptionStackTrace = true;
    
    /**
     * 异常堆栈记录行数
     */
    private int exceptionStackTraceLines = 10;

    /**
     * 编译后的排除模式
     */
    private final List<Pattern> compiledExcludePatterns = new ArrayList<>();

    /**
     * 检查URI是否匹配排除模式
     *
     * @param uri 请求URI
     * @return 是否匹配
     */
    public boolean isUriExcluded(String uri) {
        if (compiledExcludePatterns.isEmpty() && !excludePatterns.isEmpty()) {
            // 懒加载编译排除模式
            for (String pattern : excludePatterns) {
                compiledExcludePatterns.add(Pattern.compile(convertAntToRegex(pattern)));
            }
        }

        for (Pattern pattern : compiledExcludePatterns) {
            if (pattern.matcher(uri).matches()) {
                return true;
            }
        }
        return false;
    }

    /**
     * 将Ant风格路径模式转换为正则表达式
     *
     * @param antPattern Ant风格路径模式
     * @return 正则表达式
     */
    private String convertAntToRegex(String antPattern) {
        String regex = antPattern
            .replace(".", "\\.")   // 转义点号
            .replace("**", "####") // 临时替换双星号
            .replace("*", "[^/]*") // 单星号匹配任意字符，但不跨越路径分隔符
            .replace("####", ".*") // 双星号匹配任意字符，包括路径分隔符
            .replace("?", "."); // 问号匹配单个字符
        
        return "^" + regex + "$";
    }
} 